package com.wang.common.util;

import lombok.extern.log4j.Log4j2;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池的工具类
 *
 * @author wangshMac
 */
@Log4j2
public class ExecutorUtil {
    private static int CPU_COUNT = Runtime.getRuntime().availableProcessors() * 3;
    /**
     * 最小10个线程
     */
    private static int minCount = 10 ;
    /**
     * 创建一个缓存的线程池
     * 线程池启动以后不用关闭
     */
    private static ExecutorService exeSvc;

    static {
        if (CPU_COUNT < minCount) {
            CPU_COUNT = minCount;
        }
        exeSvc = new ThreadPoolExecutor(CPU_COUNT + 1, CPU_COUNT * 2 + 1,
                10L, TimeUnit.MINUTES,
                new LinkedBlockingQueue<>(1000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }

    /**
     * 提交,主线程不用等待
     */
    public static List<Object> submit(List<Callable<Object>> callList) {
        List<Object> resultList = new ArrayList<Object>();
        for (Iterator iterator = callList.iterator(); iterator.hasNext(); ) {
            Callable<Object> call = (Callable<Object>) iterator.next();
            Object resTemp = exeSvc.submit(call);
            resultList.add(resTemp);
        }
        threadInfo();
        return resultList;
    }

    /**
     * 提交,主线程不用等待
     *
     * @param call 线程列表
     * @return 结果
     */
    public static Object submit(Callable<Object> call) {
        Future<Object> obj = exeSvc.submit(call);
        threadInfo();
        return obj;
    }

    /**
     * 提交,主线程不用等待
     * @param call 线程信息
     * @return 对象
     */
    public static Object submit(Runnable call) {
        Future obj = exeSvc.submit(call);
        threadInfo();
        return obj;
    }

    public static void threadInfo() {
        if (exeSvc instanceof ThreadPoolExecutor) {
            ThreadPoolExecutor tpe = (ThreadPoolExecutor) exeSvc;
            log.info("线程信息:getActiveCount:{},getCorePoolSize:{},getPoolSize:{},getMaximumPoolSize:{},getTaskCount:{},getCompletedTaskCount:{}",
                    tpe.getActiveCount(), tpe.getCorePoolSize(),
                    tpe.getPoolSize(), tpe.getMaximumPoolSize(), tpe.getTaskCount(), tpe.getCompletedTaskCount());
        }
    }

    /**
     * 主线程得等待
     *
     * @param callList  线程列表
     * @throws InterruptedException 异常
     */
    public static List<Future<Object>> invokeAll(List<Callable<Object>> callList) throws InterruptedException {
        if (callList.size() > 0) {
            List<Future<Object>> objList = exeSvc.invokeAll(callList);
            threadInfo();
            return objList;
        }
        return Collections.emptyList();
    }

    /**
     * 关闭线程池服务
     */
    public static void shutdown() {
        exeSvc.shutdown();
    }

    public static void main(String[] args) {
        int threadLen = 10 ;
        for (int j = 0 ; j < threadLen; j ++) {
            ExecutorUtil.submit(() -> {
                for (int i = 0; i < threadLen; i++) {
                    try {
                        Thread.sleep(5 * 100);
                        threadInfo();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
    }
}
